package cn.edu.zufe.mjt.spinrg.web.servlet;


import cn.edu.zufe.mjt.spinrg.BeanPostProcessor;
import cn.edu.zufe.mjt.spinrg.Component;
import cn.edu.zufe.mjt.spinrg.web.ModelAndView;
import cn.edu.zufe.mjt.spinrg.web.annotation.Controller;
import cn.edu.zufe.mjt.spinrg.web.annotation.Param;
import cn.edu.zufe.mjt.spinrg.web.annotation.RequestMapping;
import com.alibaba.fastjson2.JSONObject;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 *
 */
@Component
public class  DispatcherServlet extends HttpServlet implements BeanPostProcessor {

    private Map<String, WebHandler> handlerMap = new HashMap<>();

    private static final Pattern PATTERN = Pattern.compile("taotao\\{(.*?)}");

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        // 根据路径寻找的 Controller 的
        // 并且，需要找到的不只是Controller 实例，还需要记录要调用的方法
        WebHandler handler = findHandler(req);
        if (handler == null) {
            resp.setContentType("text/html;charset=UTF-8");
            resp.getWriter().write("<h1>Error 你的请求没有对应的处理器</h1> <br>" + req.getRequestURL().toString());
            return;
        }
        try {
            Object controllerBean = handler.getControllerBean();

            Object[] args = resolveArgs(req, handler.getMethod());

            Method method = handler.getMethod();
            Object result = method.invoke(controllerBean,args);
            switch (handler.getResultType()) {
                case HTML -> {
                    resp.setContentType("text/html;charset=UTF-8");
                    resp.getWriter().write(result.toString());
                }
                case JSON -> {
                    resp.setContentType("application/json;charset=UTF-8");
                    resp.getWriter().write(JSONObject.toJSONString(result));
                }
                case LOCAL -> {
                    ModelAndView mv = (ModelAndView) result;
                    String view = mv.getView();
                    InputStream resourceAsStream = this.getClass().getClassLoader().getResourceAsStream(view);
                    try (resourceAsStream) {
                        String html = new String(resourceAsStream.readAllBytes());
                        html = renderTemplate(html, mv.getContext());
                        resp.setContentType("text/html;charset=UTF-8");
                        resp.getWriter().write(html);
                    }
                }
            }
        } catch (Exception e) {
            throw new ServletException("调用处理器失败", e);
        }

//        // 设置响应内容类型为HTML，字符集为UTF-8
//        resp.setContentType("text/html;charset=UTF-8");
//        // 写入响应内容，包含一个简单的HTML页面和请求的URL
//        resp.getWriter().write("<h1>Hello, Spring Boot Embedded Tomcat!</h1> <br>" + req.getRequestURL().toString());
    }

    private String renderTemplate(String template, Map<String, String> context) {
        Matcher matcher = PATTERN.matcher(template);
        StringBuilder sb = new StringBuilder();
        while (matcher.find()) {
            String key = matcher.group(1);
            String value = context.getOrDefault(key, "");
            matcher.appendReplacement(sb, Matcher.quoteReplacement(value));
        }
        matcher.appendTail(sb);
        return sb.toString();
    }

    // 实现简单的参数解析
    private Object[] resolveArgs(HttpServletRequest req, Method method) {
        Parameter[] parameters = method.getParameters();
        Object[] args = new Object[parameters.length];
        for (int i = 0; i < parameters.length; i++) {
            Parameter parameter = parameters[i];
            String value = null;
            Param param = parameter.getAnnotation(Param.class);
            if (param != null) {
                value = req.getParameter(param.value());
            } else {
                value = req.getParameter(parameter.getName());
            }
            Class<?> parameterType = parameter.getType();
            if (String.class.isAssignableFrom(parameterType)) {
                args[i] = value;
            } else if (Integer.class.isAssignableFrom(parameterType)) {
                args[i] = Integer.parseInt(value);
            } else {
                args[i] = null;
            }
        }
        return args;
    }

    private WebHandler findHandler(HttpServletRequest req) {
        // localhost:8080/a/b
//        req.getRequestURI(); // /a/b
        return handlerMap.get(req.getRequestURI());
    }

    @Override
    public Object afterInitializeBean(Object bean, String beanName) {
        if (!bean.getClass().isAnnotationPresent(Controller.class)) {
            return bean;
        }
        RequestMapping classRm = bean.getClass().getAnnotation(RequestMapping.class);
        String classUrl = classRm != null ? classRm.value() : "";
        Arrays.stream(bean.getClass().getMethods())
                .filter(method -> method.isAnnotationPresent(RequestMapping.class))
                .forEach(method -> {
                    RequestMapping methodRm = method.getAnnotation(RequestMapping.class);
                    String key = classUrl.concat(methodRm.value());
                    WebHandler webHandler = new WebHandler(bean, method);
                    if (handlerMap.put(key, webHandler) != null) {
                        throw new RuntimeException("Controller中存在相同的请求路径：" + key);
                    }
                });
        return bean;
    }
}
